/*
 * Copyright (c) xxxx my copyright message. 2022-2023. All rights reserved.
 *
 */

package com.freeworker.aiusage.exception;

import com.freeworker.aiusage.common.Constants;
import com.freeworker.aiusage.common.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * 全局异常处理器
 *
 * @author lenovo
 */
@ControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(CommonException.class)
    public ResponseEntity<Object> handleCommonException(CommonException e) {
        return ResponseEntity.status(HttpStatus.OK).body(R.fail(e.getCode(), e.getErrMsg()));
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Object> handleException(Exception e) {
        e.printStackTrace();
        return ResponseEntity.status(HttpStatus.OK).body(R.fail(CommonErrorCode.INTERNAL_SERVER_ERROR.getCode(),
                CommonErrorCode.INTERNAL_SERVER_ERROR.getErrMsg()));
    }

    /**
     * 要拦截的异常Exception
     */
    @ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class,
            HttpMessageNotReadableException.class})
    public ResponseEntity<Object> handleValidatedException(Exception exception) {
        String message;
        if (exception instanceof MethodArgumentNotValidException) {
            // BeanValidation exception
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) exception;
            message = Objects.requireNonNull(ex.getBindingResult().getFieldError()).getDefaultMessage();
            return ResponseEntity.status(HttpStatus.OK).body(R.fail(CommonErrorCode.PARAM_FORMAT_ERROR.getCode(),
                    message));
        } else if (exception instanceof ConstraintViolationException) {
            // BeanValidation GET simple param
            ConstraintViolationException ex = (ConstraintViolationException) exception;
            message = ex.getConstraintViolations().stream()
                    .map(ConstraintViolation::getMessage)
                    .collect(Collectors.joining("; "));
            return ResponseEntity.status(HttpStatus.OK).body(R.fail(CommonErrorCode.PARAM_FORMAT_ERROR.getCode(),
                    message));
        } else if (exception instanceof BindException) {
            BindException ex = (BindException) exception;
            message =
                    ex.getAllErrors().stream()
                            .map(ObjectError::getDefaultMessage)
                            .collect(Collectors.joining("; "));
            return ResponseEntity.status(HttpStatus.OK).body(R.fail(CommonErrorCode.PARAM_FORMAT_ERROR.getCode(),
                    message));
        }else if(exception instanceof  HttpMessageNotReadableException){
            // 日志
            message = CommonErrorCode.PARAM_INT_PARAM_ERROR.getErrMsg();
            if (Objects.nonNull(exception.getCause()) && Objects.nonNull(exception.getCause().getCause())) {
                String messageCause = exception.getCause().getCause().getMessage();
                log.error("[GlobalExceptionHandler]-handleValidatedException-HttpMessageNotReadableException:{}",
                        exception.getCause().getMessage());
                if (!StringUtils.isBlank(messageCause)) {
                    String[] messageArr = messageCause.split(Constants.SPIT_REGEX);
                    if (messageArr.length == 2) {
                        message = message + Constants.SPIT_REGEX + messageArr[1];
                    }
                }
            }
            return ResponseEntity.status(HttpStatus.OK).body(R.fail(CommonErrorCode.PARAM_INT_PARAM_ERROR.getCode(),
                    message));
        }
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(exception.getMessage());
    }
}
